
import React, { useContext, useState } from "react"
import { useEffect } from "react"


// https://www.bilibili.com/video/BV1x94y1d7eZ
// https://ahooks.js.org/zh-CN/hooks/use-request/basic
// 组件逻辑如何服用
// ComA ComB 有相同的一些核心业务逻辑

class ComA extends React.Component {

  state = {
    x: 0,
    y: 0,
  }

  handleMouseMove = (e) => {
    this.setState({
      x: e.pageX,
      y: e.pageY
    })
  }

  componentDidMount() {
    document.addEventListener('mousemove', this.handleMouseMove)
  }

  componentWillUnmount() {
    document.removeEventListener('mousemove', this.handleMouseMove)
  }


  render() {
    const { x, y } = this.state

    return (
      <div>
        <button>展示</button>  {x}, {y}
      </div>
    );
  }
}




class ComB extends React.Component {

  state = {
    x: 0,
    y: 0,
  }

  handleMouseMove = (e) => {
    this.setState({
      x: e.pageX,
      y: e.pageY
    })
  }

  componentDidMount() {
    document.addEventListener('mousemove', this.handleMouseMove)
  }

  componentWillUnmount() {
    document.removeEventListener('mousemove', this.handleMouseMove)
  }


  render() {
    const { x, y } = this.state

    return (
      <span
        style={{
          border: "1px solid red",
          left: x,
          top: y,
          position: "absolute"
        }}
      >
        B 组件
      </span>
    )
  }
}



// 高阶组件
// 本质:高阶组件其实是一个函数参数是一个组件返回值同样是一个组件
// 函数内部维护一个内部的包装组件在这个组件中需要维护复用的逻辑状态并且把状态传入我们参数组件中


const withHocComponent = (Com) => {

  class WrapperCom extends React.Component {

    state = {
      x: 0,
      y: 0,
    }

    handleMouseMove = (e) => {
      this.setState({
        x: e.pageX,
        y: e.pageY
      })
    }

    componentDidMount() {
      document.addEventListener('mousemove', this.handleMouseMove)
    }

    componentWillUnmount() {
      document.removeEventListener('mousemove', this.handleMouseMove)
    }


    render() {

      return (
        // 渲染参数组件，并且将状态都反回
        <Com {...this.state} />
      )
    }
  }


  // 返回一个组件
  return WrapperCom
}


const AshowCom = (props) => {


  return (
    <div>
      <button>展示</button>  {props.x}, {props.y}
    </div>
  )
}


const BshowCom = (props) => {

  const { x, y } = props

  return (
    <span
      style={{
        border: "1px solid red",
        left: x,
        top: y,
        position: "absolute"
      }}
    >
      B 组件
    </span>
  )
}


const WrapperA = withHocComponent(AshowCom)
const WrapperB = withHocComponent(BshowCom)




// render props
class WithPropsomponent extends React.Component {

  state = {
    x: 0,
    y: 0,
  }

  handleMouseMove = (e) => {
    this.setState({
      x: e.pageX,
      y: e.pageY
    })
  }

  componentDidMount() {
    document.addEventListener('mousemove', this.handleMouseMove)
  }

  componentWillUnmount() {
    document.removeEventListener('mousemove', this.handleMouseMove)
  }


  render() {

    return (
      <div>
        {
          this.props.children(this.state)
        }
      </div>
    )
  }

}





// hook方案

const useMouse = () => {

  const [pos, setPos] = useState({
    x: 0,
    y: 0
  })

  const handleMouseMove = (e) => {
    setPos({
      x: e.pageX,
      y: e.pageY
    })
  }

  useEffect(() => {

    document.addEventListener('mousemove', handleMouseMove)


    return () => {
      document.removeEventListener('mousemove', handleMouseMove)
    }
  }, [])

  return pos
}




const HookAshowCom = () => {

  const pos = useMouse()


  console.log('HookAshowCom render');
  return (
    <div>
      <button>展示</button>  {pos.x}, {pos.y}
    </div>
  )
}


const HookBshowCom = () => {

  const pos = useMouse()

  console.log('HookBshowCom render');
  return (
    <span
      style={{
        border: "1px solid red",
        left: pos.x,
        top: pos.y,
        position: "absolute"
      }}
    >
      B 组件
    </span>
  )
}


function HocApp() {

  return (
    <>
      {/* <div>
        <ComA />
        <ComB />
      </div> */}


      <div>
        {/* <ComA />
        <ComB /> */}

        {/* <WrapperA />
        <WrapperB /> */}


        {/* <WithPropsomponent>
          {
            ({x, y}) => {
              return (
                <AshowCom x={x} y={y}/>
              )
            }
          }
        </WithPropsomponent>

        <WithPropsomponent>
          {
            ({x, y}) => {
              return (
                <BshowCom x={x} y={y}/>
              )
            }
          }
        </WithPropsomponent> */}


        <HookAshowCom />
        <HookBshowCom />

      </div>
    </>
  )

}



export default HocApp

